import binascii
import json
import logging
import os

from rest_framework import HTTP_HEADER_ENCODING
from rest_framework import exceptions
from rest_framework.authentication import TokenAuthentication
from django.contrib.auth.models import User
from django_redis import get_redis_connection

redis_connect = get_redis_connection("default")
logger = logging.getLogger("default")


class Token(object):

    @staticmethod
    def create_token(user):
        token = binascii.hexlify(os.urandom(20)).decode()  # 生成token 的方式
        _dict = {'id': user.id,
                 'username': user.username,
                 'email': user.email}
        redis_connect.set(token, json.dumps(_dict), 60 * 60 * 3)  # 存redis 3个小时
        logger.info("create_token token = {}".format( redis_connect.get(token)))
        return token

    @staticmethod
    def remove_token(token_key):
        caches_data = redis_connect.get(token_key)
        logger.info("caches_data = {}".format(caches_data))
        if caches_data:
            redis_connect.delete(token_key)
        return caches_data


# token认证
class RedisTokenAuthentication(TokenAuthentication):

    def authenticate(self, request):
        token_key = get_header_token(request)
        if not token_key:
            return None, None
        key_list = redis_connect.keys()
        if token_key not in key_list:
            msg = 'Invalid token header. No credentials provided.'
            raise exceptions.AuthenticationFailed(msg)
        return self.authenticate_credentials(token_key)

    def authenticate_credentials(self, key):

        user_data = redis_connect.get(key)
        print("token_key = {}".format(key))
        if user_data:
            user_dict = json.loads(user_data)
            user_obj = User.objects.filter(id=user_dict['id'])
            if user_obj:
                return user_obj.first(), key
        raise exceptions.AuthenticationFailed('Invalid credentials')


def get_header_token(request):
    token_key = request.META.get('HTTP_TOKEN', b'')
    if isinstance(token_key, str):
        # Work around django test client oddness
        token_key = token_key.encode(HTTP_HEADER_ENCODING)
    return token_key